package com.dragon.modules.yuegou.service.impl.coupon;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.exception.DragonException;
import com.dragon.common.web.PageRequest;
import com.dragon.modules.yuegou.entity.coupon.CouponEntity;
import com.dragon.modules.yuegou.entity.coupon.CouponScopeSpuEntity;
import com.dragon.modules.yuegou.entity.coupon.CouponTemplateEntity;
import com.dragon.modules.yuegou.entity.coupon.CouponTemplateRandomEntity;
import com.dragon.modules.yuegou.entity.coupon.CouponTemplateStockEntity;
import com.dragon.modules.yuegou.entity.coupon.CouponTemplateStockRecordEntity;
import com.dragon.modules.yuegou.entity.product.SkuEntity;
import com.dragon.modules.yuegou.entity.product.SpuEntity;
import com.dragon.modules.yuegou.enums.SkuType;
import com.dragon.modules.yuegou.enums.code.BusinessCode;
import com.dragon.modules.yuegou.enums.code.CouponCode;
import com.dragon.modules.yuegou.enums.coupon.CouponSourceType;
import com.dragon.modules.yuegou.enums.coupon.CouponTemplateCheckedStatus;
import com.dragon.modules.yuegou.enums.coupon.CouponTemplateDivideType;
import com.dragon.modules.yuegou.enums.coupon.CouponTemplateFormat;
import com.dragon.modules.yuegou.enums.coupon.CouponTemplateOwnerType;
import com.dragon.modules.yuegou.enums.coupon.CouponTemplateScope;
import com.dragon.modules.yuegou.enums.coupon.CouponTemplateShelfStatus;
import com.dragon.modules.yuegou.enums.coupon.CouponTemplateStockRecordStockType;
import com.dragon.modules.yuegou.enums.coupon.CouponTemplateStockRecordType;
import com.dragon.modules.yuegou.enums.coupon.CouponTemplateTimeLimitType;
import com.dragon.modules.yuegou.enums.coupon.CouponTemplateType;
import com.dragon.modules.yuegou.enums.coupon.CouponType;
import com.dragon.modules.yuegou.enums.product.FilterType;
import com.dragon.modules.yuegou.enums.product.SpuPackageType;
import com.dragon.modules.yuegou.enums.product.SpuPublishStatus;
import com.dragon.modules.yuegou.enums.product.SpuShowModule;
import com.dragon.modules.yuegou.enums.product.SpuVerifyStatus;
import com.dragon.modules.yuegou.mapper.coupon.CouponTemplateMapper;
import com.dragon.modules.yuegou.model.coupon.ChannelCode;
import com.dragon.modules.yuegou.model.coupon.Coupon;
import com.dragon.modules.yuegou.model.coupon.CouponScopePark;
import com.dragon.modules.yuegou.model.coupon.CouponTemplate;
import com.dragon.modules.yuegou.model.coupon.CouponTemplateRandom;
import com.dragon.modules.yuegou.model.coupon.CouponTemplateStock;
import com.dragon.modules.yuegou.model.coupon.CouponTemplateStockRecord;
import com.dragon.modules.yuegou.model.coupon.CurrencyCode;
import com.dragon.modules.yuegou.model.coupon.SceneCode;
import com.dragon.modules.yuegou.model.park.Parking;
import com.dragon.modules.yuegou.model.product.Spu;
import com.dragon.modules.yuegou.query.coupon.CouponParkQuery;
import com.dragon.modules.yuegou.query.coupon.CouponQuery;
import com.dragon.modules.yuegou.query.coupon.CouponScopeSpuQuery;
import com.dragon.modules.yuegou.query.coupon.CouponTemplateQuery;
import com.dragon.modules.yuegou.query.coupon.CouponTemplateRandomQuery;
import com.dragon.modules.yuegou.query.product.SpuQuery;
import com.dragon.modules.yuegou.service.coupon.CouponScopeParkService;
import com.dragon.modules.yuegou.service.coupon.CouponScopeSpuService;
import com.dragon.modules.yuegou.service.coupon.CouponService;
import com.dragon.modules.yuegou.service.coupon.CouponTemplateRandomService;
import com.dragon.modules.yuegou.service.coupon.CouponTemplateService;
import com.dragon.modules.yuegou.service.coupon.CouponTemplateStockRecordService;
import com.dragon.modules.yuegou.service.coupon.CouponTemplateStockService;
import com.dragon.modules.yuegou.service.product.SkuService;
import com.dragon.modules.yuegou.service.product.SpuService;
import com.dragon.modules.yuegou.web.Check;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
 * 优惠券模板 服务实现
 *
 * @author pbuilder generated
 * @date 2019-02-28 18:30:17
 * @version 2.0
 */
@Slf4j
@Service("coupCouponTemplateService")
@CacheConfig(cacheNames = CouponTemplateServiceImpl.COUPON_TEMPLATE_DETAIL_CACHE_NAME)
public class CouponTemplateServiceImpl
		extends ServiceImpl<CouponTemplateMapper, CouponTemplateEntity>
		implements CouponTemplateService {

	/**
	 * 模板详情缓存名称
	 */
	protected static final String COUPON_TEMPLATE_DETAIL_CACHE_NAME = "CouponTemplateDetail";

	private Cache couponTemplateDetailCache;

	@Autowired
	private CouponScopeParkService couponScopeParkService;

	@Autowired
	private CouponScopeSpuService couponScopeSpuService;

	@Autowired
	private CouponTemplateStockService couponTemplateStockService;

	@Autowired
	private CouponTemplateStockRecordService couponTemplateStockRecordService;

	@Autowired
	private CouponService couponService;

	@Autowired
	private CouponTemplateRandomService couponTemplateRandomService;

	@Autowired
	private SpuService spuService;

	@Autowired
	private SkuService skuService;
	
	@Autowired
	public void setCouponTemplateDetailCache(CacheManager cacheManager) {
		this.couponTemplateDetailCache = cacheManager.getCache(COUPON_TEMPLATE_DETAIL_CACHE_NAME);
	}

	@Override
	public void evictCache(String couponTemplateId) {
		couponTemplateDetailCache.evict(couponTemplateId);
	}

	@Override
	public CouponTemplate detail(String couponTemplateId) {
		Check.notNull(couponTemplateId, "id is required");
		CouponTemplate couponTemplate = couponTemplateDetailCache.get(couponTemplateId, CouponTemplate.class);
		if (couponTemplate != null) {
			return couponTemplate;
		}
		CouponTemplateEntity entity = getById(couponTemplateId);
		if (entity == null) {
			return null;
		}
		couponTemplate = new CouponTemplate(entity);
		couponTemplate.setScopeSpuList(couponScopeSpuService.getSpuList(couponTemplateId));
		couponTemplate.setStatus(checkStock(couponTemplate)?0:1);
		couponTemplateDetailCache.put(couponTemplateId, couponTemplate);
		return couponTemplate;
	}

	@Transactional
	@Override
	public void createCouponTemplate(CouponParkQuery couponParkQuery) {
		CouponTemplateQuery query = couponParkQuery.getCouponTemplateQuery();
		List<Parking> parkingList = couponParkQuery.getParkingList();
		// 校验数据
		checkData(query, parkingList);
		// 保存停车券模板
		CouponTemplate couponTemplate = new CouponTemplate();
		couponTemplate.setTitle(query.getTitle());
		couponTemplate.setOwnerType(CouponTemplateOwnerType.GROUP);
		couponTemplate.setBusdId(query.getBusdId());
		couponTemplate.setGroupId("");
		couponTemplate.setTimeLimitType(CouponTemplateTimeLimitType.VALID_DAYS);
		couponTemplate.setValidDays(query.getValidDays());
		couponTemplate.setScope(CouponTemplateScope.BUSINESS_DISTRICT);
		SceneCode sceneCode = new SceneCode(7);
		sceneCode.setPark(true);
		couponTemplate.setScene(sceneCode.getCode());
		CurrencyCode currencyCode = new CurrencyCode(4);
		currencyCode.setThirdWallet(true);
		couponTemplate.setCurrency(currencyCode.getCode());
		ChannelCode code = new ChannelCode(0);
		code.setBuy(true);
		code.setPoints(true);
		couponTemplate.setChannel(code.getCode());
		couponTemplate.setType(CouponTemplateType.PARK);
		couponTemplate.setFormat(CouponTemplateFormat.DEDUCATION);
		couponTemplate.setReductionMount(query.getReductionMount());
		if (query.getShelfStatus()!=null){
			couponTemplate.setShelfStatus(query.getShelfStatus());
		}else {
			couponTemplate.setShelfStatus(CouponTemplateShelfStatus.OFF_SHELF);
		}

		couponTemplate.setDiscountRate(new BigDecimal("1"));
		couponTemplate.setLowerLimit(new BigDecimal("-1"));
		couponTemplate.setUpperLimit(new BigDecimal("-1"));
		couponTemplate.setPersonalLimit(-1);
		couponTemplate.setMemberLevelLimit(-1);
		couponTemplate.setAllowSale(true);
		couponTemplate.setDel(false);
		couponTemplate.setCheckedStatus(CouponTemplateCheckedStatus.PASSED);
		couponTemplate.setDiscription(query.getDiscription());
		this.save(couponTemplate);
		if (parkingList != null && parkingList.size() > 0) {
			for (int i = 0; i < parkingList.size(); i++) {
				Parking parking = parkingList.get(i);
				CouponScopePark couponScopePark = new CouponScopePark();
				couponScopePark.setCouponTemplateId(couponTemplate.getId());
				couponScopePark.setParkId(parking.getId());
				couponScopeParkService.save(couponScopePark);
			}
		}
	}

	private void checkData(CouponTemplateQuery query, List<Parking> parkingList) {
		if (query == null) {
			throw new DragonException(CouponCode.COUPONINFO);
		}
		if (parkingList == null) {
			throw new DragonException(CouponCode.PARKLIST);
		}
		Check.notNull(query.getBusdId(), BusinessCode.BUSDID_NOTNULL.getMessage());
		Check.notNull(query.getTitle(), "title is required");
		Check.length(query.getTitle(), 0, 15, "优惠券名称限15个字");
		Check.notNull(query.getValidDays(), "validDays is required");
		Check.notNull(query.getReductionMount(), "reductionMount is required");
	}

	@Override
	public CouponTemplate getOpenTicket(String busdId) {
		Check.notEmpty(busdId, BusinessCode.BUSDID_NOTNULL.getMessage());
		// 查询商圈开启兑换小票的停车券
		CouponTemplateQuery couponTemplateQuery = new CouponTemplateQuery();
		couponTemplateQuery.setBusdId(busdId);
		ChannelCode code = new ChannelCode(0);
		code.setBuy(true);
		code.setPoints(true);
		code.setTickets(true);
		couponTemplateQuery.setChannel(code.getCode());
		CouponTemplateEntity template = getOne(couponTemplateQuery.toQueryWrapper());
		if (template == null) {
			throw new DragonException(CouponCode.NO_SET_POINT_TEMPLATE);
		}
		return new CouponTemplate(template);
	}

	@Override
	public List<CouponTemplate> searchParkCoupon(String busdId,String title) {
		return baseMapper.searchParkCoupon(busdId, title);
	}

	@Override
	public Integer getSpuCashCouponListNum(String spuId) {
		List<CouponTemplate> list = getSpuCashCouponList(spuId,false);
		return CollectionUtils.isEmpty(list) ? 0 : list.size();
	}

	@Override
	public List<CouponTemplate> getSpuCashCouponList(String spuId,boolean status) {
		Check.notNull(spuId, "spuId is required");
		SpuEntity spu = spuService.getById(spuId);

		List<CouponTemplate> collect = baseMapper.searchList(spu.getBusdId(),status?"1":"0").stream()
				.filter((CouponTemplate t) -> getScopeSpu(detail(t.getId()), spuId)).collect(Collectors.toList());
		collect.forEach(a -> {
			if (checkStock(a)) {
				a.setStatus(0);
			} else {
				a.setStatus(1);
			}
		});
		return collect;
	}

	/***
	 * 校验是否存在库存
	 *
	 * @param couponTemplate
	 * @return
	 */
	private boolean checkStock(CouponTemplate couponTemplate) {
		CouponTemplateStockEntity stock = couponTemplateStockService.getById(couponTemplate.getId());
		if (stock == null || stock.getStockSurplus() <1) {
			return false;
		}
		 if (CouponTemplateFormat.RANDOM.equals(couponTemplate.getFormat())) {
			CouponTemplateRandomQuery query = new CouponTemplateRandomQuery();
			query.setCouponTemplateId(couponTemplate.getId());
			List<CouponTemplateRandomEntity> list = couponTemplateRandomService.list(query.toQueryWrapper());
			log.debug("模板ID={},随机列表={}", couponTemplate.getId(), JSON.toJSONString(list));
			for (CouponTemplateRandomEntity couponTemplateRandom : list) {
				if (couponTemplateRandom.getValidStatus()) {
					return true;
				}
			}
			return false;
		 } else if (CouponTemplateFormat.DEDUCATION.equals(couponTemplate.getFormat())) {
			 return true;
		 }
		return false;
	}

	@Override
	public boolean getScopeSpu(CouponTemplate couponTemplate, String spuId) {
		if (couponTemplate.getScope() == CouponTemplateScope.EXCLUDE_SPU) {
			return !couponTemplate.getScopeSpuList().stream().map(Spu::getId).collect(Collectors.toList()).contains(spuId);
		} else if (couponTemplate.getScope() == CouponTemplateScope.SPU) {
			return couponTemplate.getScopeSpuList().stream().map(Spu::getId).collect(Collectors.toList()).contains(spuId);
		} else if (couponTemplate.getScope() == CouponTemplateScope.ALL) {
			return true;
		}
		return false;
	}

	@Override
	@Transactional
	public BigDecimal receive(String memberId, String couponTemplateId) {
		// 先给券给用户，如果后续扣库存失败，将减少库存事物回滚带来的死锁问题
		// 给券给用户
		Coupon coupon = couponService.createCoupon(null, memberId, couponTemplateId, CouponSourceType.RECEIVE);
		// 扣库存
		couponTemplateStockService.editStock(couponTemplateId, -1);
		// 新增库存记录
		CouponTemplateStockRecordEntity stockRecordEntity = new CouponTemplateStockRecordEntity();
		stockRecordEntity.setType(CouponTemplateStockRecordType.RECEIVE);
		stockRecordEntity.setChange(1);
		stockRecordEntity.setCreatedBy(memberId);
		couponTemplateStockRecordService.save(stockRecordEntity);
		return coupon.getReductionMount();
	}

	@Override
	@Transactional
	public List<Coupon> issueCoupon(List<String> memberIdList, String couponTemplateId,Integer num) {
		// 先给券给用户，如果后续扣库存失败，将减少库存事物回滚带来的死锁问题
		List<Coupon> couponList = new ArrayList<>();
		for (int i = 0 ;i <num ;i++){
			couponList.addAll(memberIdList.stream().map(memberId ->{
				// 给券给用户
				Coupon coupon = couponService.createCoupon(null, memberId, couponTemplateId, CouponSourceType.WELFARE);
				// 扣库存
				couponTemplateStockService.editStock(couponTemplateId, -1);
				// 新增库存记录
				CouponTemplateStockRecordEntity stockRecordEntity = new CouponTemplateStockRecordEntity();
				stockRecordEntity.setType(CouponTemplateStockRecordType.RECEIVE);
				stockRecordEntity.setChange(1);
				stockRecordEntity.setCreatedBy(memberId);
				couponTemplateStockRecordService.save(stockRecordEntity);

				return coupon;
			}).collect(Collectors.toList()));
		}
		return couponList;
	}

	@Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateRandom(CouponTemplateRandom random){
        random.setValidStatus(false);
        couponTemplateRandomService.updateById(random);
    }
	@Override
	public boolean verifyOrderCash(String couponTemplateId, BigDecimal orderFee) {
		CouponTemplate couponTemplate = this.detail(couponTemplateId);
		log.debug("模板ID={},券限制={},订单金额={}", couponTemplateId, couponTemplate.getLowerLimit(), orderFee);
		return couponTemplate.getLowerLimit().signum() == -1 || couponTemplate.getLowerLimit().compareTo(orderFee) < 1;
	}

	@Override
	public boolean verifyReceiveStatus(String memberId, String couponTemplateId) {
		CouponTemplate couponTemplate = this.detail(couponTemplateId);
		// 判断是否在结束时间内
		if (couponTemplate.getEndTime() != null && couponTemplate.getEndTime().isBefore(LocalDateTime.now())) {
			return false;
		}
		CouponQuery query = new CouponQuery();
		query.setMemberId(memberId);
		query.setCouponTemplateId(couponTemplateId);
		List<CouponEntity> list = couponService.list(query.toQueryWrapper());
		// 会员从来没有领取过券
		if (CollectionUtils.isEmpty(list)) {
			return true;
		}
		// 用户领取总数量超过最大限制
		if (couponTemplate.getPersonalLimit() > 0 && list.size() >= couponTemplate.getPersonalLimit()) {
			return false;
		}
		// 用户当日领取数量超过最大限制
		if (couponTemplate.getPersonalDayLimit() > 0) {
			Integer dayReceiveNum = list.stream()
					.filter((CouponEntity c) -> c.getCreatedTime().toLocalDate().isEqual(LocalDate.now()))
					.collect(Collectors.toList()).size();
			if (couponTemplate.getPersonalDayLimit() <= dayReceiveNum) {
				return false;
			}
		}
		return true;
	}

	public Integer checkReceiveQul(String memberId, String couponTemplateId) {
		CouponTemplateStockEntity couponTemplateStock = couponTemplateStockService.getById(couponTemplateId);
		if (couponTemplateStock == null || couponTemplateStock.getStockSurplus() < 1) {
			return 2;
		}
		return 0;
	}

	@Override
	@Transactional
	public void createCashCoupon(CouponTemplate couponTemplate) {
		// 校验
		checkCashCoupon(couponTemplate);

		// 充填基础信息
		couponTemplate.setOwnerType(CouponTemplateOwnerType.GROUP);
		couponTemplate.setType(CouponTemplateType.CASH);
		// 无折扣
		couponTemplate.setDiscountRate(new BigDecimal(1));
		// 会员等级限制无
		couponTemplate.setMemberLevelLimit(-1);
		// 允许售卖
		couponTemplate.setAllowSale(true);
		// 默认上架
		if (couponTemplate.getShelfStatus()==null){
			couponTemplate.setShelfStatus(CouponTemplateShelfStatus.ON_SHELF);
		}

		// 审核状态
		couponTemplate.setCheckedStatus(CouponTemplateCheckedStatus.PASSED);
		couponTemplate.setScene(6);
		couponTemplate.setCurrency(0);
		couponTemplate.setChannel(0);
		couponTemplate.setDel(false);
		baseMapper.insert(couponTemplate);

		// 插入可使用的spu信息
		List<CouponScopeSpuEntity> entities = new ArrayList<>();
		if (CollectionUtils.isNotEmpty(couponTemplate.getScopeSpuIdList())) {
			for (String spuId : couponTemplate.getScopeSpuIdList()) {
				CouponScopeSpuEntity couponScopeSpu = new CouponScopeSpuEntity();
				couponScopeSpu.setCouponTemplateId(couponTemplate.getId());
				couponScopeSpu.setSpuId(spuId);
				entities.add(couponScopeSpu);
			}
		}
		couponScopeSpuService.saveBatch(entities);

		// 随机劵
		if (CouponTemplateFormat.RANDOM.equals(couponTemplate.getFormat())) {
			List<CouponTemplateRandom> list = couponTemplate.getRandomList();
			if (CollectionUtils.isNotEmpty(list)) {
				List<CouponTemplateRandomEntity> randomEntities = new ArrayList<>();
				for (CouponTemplateRandom temp : list) {
					temp.setCouponTemplateId(couponTemplate.getId());
					temp.setNowFee(BigDecimal.ZERO);
					temp.setNowNum(0);
					temp.setValidStatus(true);
					randomEntities.add(temp);
				}
				couponTemplateRandomService.saveBatch(randomEntities);
			}
		}
		// 添加模板库存
		CouponTemplateStock couponTemplateStock = new CouponTemplateStock();
		couponTemplateStock.setId(couponTemplate.getId());
		couponTemplateStock.setStockTotal(couponTemplate.getStockTotal());
		couponTemplateStock.setStockSurplus(couponTemplate.getStockTotal());
		couponTemplateStock.setStockUse(0);
		couponTemplateStock.setSaleStock(0);
		couponTemplateStock.setSaleTotal(0);
		couponTemplateStock.setGranted(0);
		couponTemplateStock.setGrantStock(0);
		couponTemplateStock.setGrantTotal(0);
		couponTemplateStock.setVersion(0);
		couponTemplateStock.setModifiedTime(LocalDateTime.now());
		couponTemplateStockService.save(couponTemplateStock);
		// 新建库存变更
		CouponTemplateStockRecord couponTemplateStockRecord = new CouponTemplateStockRecord();
		couponTemplateStockRecord.setCouponTemplateId(couponTemplate.getId());
		couponTemplateStockRecord.setTotal(couponTemplate.getStockTotal());
		couponTemplateStockRecord.setStock(couponTemplate.getStockTotal());
		couponTemplateStockRecord.setChange(couponTemplate.getStockTotal());
		couponTemplateStockRecord.setStockType(CouponTemplateStockRecordStockType.IN);
		couponTemplateStockRecord.setType(CouponTemplateStockRecordType.INIT);
		couponTemplateStockRecordService.save(couponTemplateStockRecord);

	}

	private void checkCashCoupon(CouponTemplate couponTemplate) {
		Check.notNull(couponTemplate.getFormat(), "优惠形式不能为空");
		Check.notEmpty(couponTemplate.getTitle(), "优惠劵名称不能为空");
		Check.notNull(couponTemplate.getStockTotal(), "发放总量不能为空");
		Check.notNull(couponTemplate.getScope(), "适用商品类型不能为空");
		if (CouponTemplateFormat.RANDOM.equals(couponTemplate.getFormat())) {
			this.checkCashCouponRandom(couponTemplate);
		}
		if (!CouponTemplateScope.ALL.equals(couponTemplate.getScope())) {
			Check.notNull(couponTemplate.getScopeSpuIdList(), "商品spuId列表不能为空");
		}
		if (couponTemplate.getLowerLimit() == null) {
			couponTemplate.setLowerLimit(new BigDecimal(-1));
		}
		couponTemplate.setUpperLimit(new BigDecimal(-1));
		Check.notNull(couponTemplate.getReductionMount(), "减免金额不能为空");
		Check.notNull(couponTemplate.getTimeLimitType(), "使用时间类型不能为空");
		if (CouponTemplateTimeLimitType.FIXED_RANGE.equals(couponTemplate.getTimeLimitType())) {
			Check.notNull(couponTemplate.getStartTime(), "生效开始时间不能为空");
			Check.notNull(couponTemplate.getEndTime(), "生效结束时间不能为空");
		} else if (CouponTemplateTimeLimitType.VALID_DAYS.equals(couponTemplate.getTimeLimitType())) {
			Check.notNull(couponTemplate.getValidHours(), "失效时间不能为空");
		}
		Check.notEmpty(couponTemplate.getImgUrl(), "优惠劵图片不能为空");
		if (couponTemplate.getPersonalLimit() == null) {
			couponTemplate.setPersonalLimit(-1);
		}
		if (couponTemplate.getPersonalDayLimit() == null) {
			couponTemplate.setPersonalDayLimit(-1);
		}
		// 次数限制不能为空
		Check.notNull(couponTemplate.getDivideType(), "分摊方式不能为空");
		Check.notNull(couponTemplate.getDivideMerchant(), "商户分摊不能为空");
		Check.notNull(couponTemplate.getDivideGroup(), "平台分摊不能为空");
		if (CouponTemplateDivideType.CASH.equals(couponTemplate.getDivideType())) {
			BigDecimal add = couponTemplate.getDivideMerchant().add(couponTemplate.getDivideGroup());
			if (add.compareTo(couponTemplate.getReductionMount()) != 0) {
				throw new DragonException(CouponCode.MERCHANT_GROUP_EQUAL);
			}
		}
		if (CouponTemplateDivideType.SCALE.equals(couponTemplate.getDivideType())) {
			BigDecimal merchantDecimal = couponTemplate.getDivideMerchant().divide(new BigDecimal(100));
			couponTemplate.setDivideMerchant(merchantDecimal);
			BigDecimal groupDecimal = couponTemplate.getDivideGroup().divide(new BigDecimal(100));
			couponTemplate.setDivideGroup(groupDecimal);
			BigDecimal add = merchantDecimal.add(groupDecimal);
			if (add.compareTo(new BigDecimal(1)) != 0) {
				throw new DragonException(CouponCode.MERCHANT_GROUP_EQUAL);
			}
		}
		Check.notNull(couponTemplate.getViewStartTime(), "展示开始时间不能为空");
		Check.notNull(couponTemplate.getViewEndTime(), "展示结束时间不能为空");
		Check.notNull(couponTemplate.getAllowCpys(), "是否叠加不能为空");

	}

	private void checkCashCouponRandom(CouponTemplate couponTemplate) {
		Check.notNull(couponTemplate.getUpperDiscount(), "抵扣金额上限不能为空");
		Check.notNull(couponTemplate.getLowerDiscount(), "抵扣金额下限不能为空");
		// 校验随机劵
		List<CouponTemplateRandom> list = couponTemplate.getRandomList();
		// 总数量
		if (CollectionUtils.isEmpty(list)) {
			return;
		}

		Integer totalSum = 0;
		BigDecimal totalAmount = BigDecimal.ZERO;
		for (CouponTemplateRandom temp : list) {
			totalSum += temp.getLimitMaxNum();
			totalAmount = totalAmount.add(temp.getLimitMaxFee());
		}
		if (totalSum > couponTemplate.getStockTotal()) {
			throw new DragonException(CouponCode.LADDERS_TOTAL_TEMP_TOTAL_SUM);
		}

		if (totalAmount.compareTo(couponTemplate.getReductionMount()) >0) {
			throw new DragonException(CouponCode.LADDERS_TOTAL_TEMP_TOTAL_AMOUNT);
		}
		for (CouponTemplateRandom temp : list) {
			// 判断集合数据是否超过上下线
			if (temp.getEndFee().compareTo(couponTemplate.getUpperDiscount()) >0
					|| temp.getEndFee().compareTo(couponTemplate.getLowerDiscount()) <0) {
				throw new DragonException(CouponCode.COUPON_AMOUNT_EXCEEDS_LIMIT);
			}
			if (temp.getBeginFee().compareTo(couponTemplate.getUpperDiscount()) >0
					|| temp.getBeginFee().compareTo(couponTemplate.getLowerDiscount()) <0) {
				throw new DragonException(CouponCode.COUPON_AMOUNT_EXCEEDS_LIMIT);
			}
		}
	}

	@Override
	@Transactional
	public void editCashCoupon(CouponTemplate couponTemplate) {
		if (couponTemplate.getScope() != null) {
			// 删除优惠劵商品关系
			CouponScopeSpuQuery query = new CouponScopeSpuQuery();
			query.setCouponTemplateId(couponTemplate.getId());
			List<CouponScopeSpuEntity> list = couponScopeSpuService.list(query.toQueryWrapper());
			couponScopeSpuService.removeBatchByIds(list.stream().map(CouponScopeSpuEntity::getId).collect(Collectors.toList()));
			// 插入可使用的spu信息
			List<CouponScopeSpuEntity> entities = new ArrayList<>();
			if (CollectionUtils.isNotEmpty(couponTemplate.getScopeSpuIdList())) {
				for (String spuId : couponTemplate.getScopeSpuIdList()) {
					CouponScopeSpuEntity couponScopeSpu = new CouponScopeSpuEntity();
					couponScopeSpu.setCouponTemplateId(couponTemplate.getId());
					couponScopeSpu.setSpuId(spuId);
					entities.add(couponScopeSpu);
				}
			}
			// 批量插入优惠劵商品信息
			if (CollectionUtils.isNotEmpty(entities)) {
				couponScopeSpuService.saveBatch(entities);
			}

		}
		if (couponTemplate.getViewModel() == null) {
			baseMapper.modifyViewModel(couponTemplate.getId());
		}
		baseMapper.updateById(couponTemplate);
		evictCache(couponTemplate.getId());
	}

	@Override
	public void editStatus(String id, Integer status) {
		Check.notEmpty(id, "模板Id不能为空");
		Check.notNull(status, "上下架状态不能为空");
		// 查询优惠劵模板信息
		CouponTemplateEntity template = getById(id);
		if (status == 0) {
			// 下架
			template.setShelfStatus(CouponTemplateShelfStatus.OFF_SHELF);
		} else if (status == 1) {
			// 上架
			template.setShelfStatus(CouponTemplateShelfStatus.ON_SHELF);
		}
		baseMapper.updateById(template);
		evictCache(id);
	}

	@Override
	public IPage<CouponTemplate> districtList(PageRequest page, CouponTemplateQuery query) {
		IPage<CouponTemplateEntity> entityIPage = new Page<>(page.getPage(),page.getSize(),page.getCount());
		QueryWrapper<CouponTemplateEntity> wrapper = query.toQueryWrapper();
		wrapper.orderByDesc(CouponTemplateEntity.COL_CREATED_TIME);
		IPage<CouponTemplateEntity> templateEntityIPage = baseMapper.selectPage(entityIPage,wrapper);
		return templateEntityIPage.convert(CouponTemplate::new);
	}
	

    @Override
    public List<CouponTemplate> searchList(CouponTemplateQuery query) {
		List<CouponTemplateEntity> entities = baseMapper.selectList(query.toQueryWrapper());
        return entities.stream().map(CouponTemplate::new).collect(Collectors.toList());
    }

    @Override
	public List<Spu> couponSpuList(String id,String busdId) {
		Check.notEmpty(id, "模板Id不能为空");
		List<SpuEntity> spus = new ArrayList<>();
		// 查询优惠劵模板信息
		CouponTemplateEntity template = getById(id);
		// 判断限制类型
		SpuQuery query = new SpuQuery();
		query.setShowModule(SpuShowModule.GOODS);
		query.setSkuType(SkuType.GOODS);
		query.setPackageType(SpuPackageType.NO);
		query.setBusdId(busdId);
		query.setDel(false);
		List<SpuEntity> list = spuService.list(query.toQueryWrapper());
		// 查询优惠劵关联商品
		CouponScopeSpuQuery scopeSpuQuery = new CouponScopeSpuQuery();
		scopeSpuQuery.setCouponTemplateId(id);
		List<String> spuIds = couponScopeSpuService.list(scopeSpuQuery.toQueryWrapper()).stream().map(scopeSpu -> scopeSpu.getSpuId())
				.collect(Collectors.toList());
		if (CouponTemplateScope.ALL.equals(template.getScope())) {
			spus.addAll(list);
		} else if (CouponTemplateScope.SPU.equals(template.getScope())) {
			// 查询优惠劵商品关联表
			List<SpuEntity> sps = spuService.listByIds(spuIds);
			spus.addAll(sps);
		} else if (CouponTemplateScope.EXCLUDE_SPU.equals(template.getScope())) {
			// 查询优惠劵商品关联表
			List<SpuEntity> collect = list.stream().filter(spu -> {
				Boolean ble = true;
				for (String spuId : spuIds) {
					if (spuId.equals(spu.getId())) {
						ble = false;
						break;
					}
				}
				return ble;
			}).collect(Collectors.toList());
			spus.addAll(collect);
		}
		return spus.stream().map(Spu::new).collect(Collectors.toList());
	}

	@Override
	public IPage<Spu> searchPageSpu(PageRequest arg0, String couponTemplateId) {
		CouponTemplateEntity template = getById(couponTemplateId);
		if(null == template) {
			throw new DragonException(CouponCode.SELECT_COUPON_NUM_ERROR);
		}
		String busdId = template.getBusdId();
		IPage<Spu> page = new Page<>();
		switch (template.getScope()) {
			//所有商品
			case ALL:
				return spuService.productSearch(arg0, FilterType.DEFAULT, busdId, null, null);
			//指定商品
			case SPU:
				page = getScopeSpuPage(couponTemplateId, arg0);
				break;
			//排除指定商品
			case EXCLUDE_SPU:
				page = getExcludeSpuPage(couponTemplateId, arg0,template.getBusdId());
				break;
		}
		return page;
	}

	@Override
	public List<Coupon> searchCouponByOrder(BigDecimal money, List<String> skuIds, String memberId, String busdId) {
		List<Coupon> list = new ArrayList<>();
		CouponQuery query = new CouponQuery();
		query.setBusdId(busdId);
		query.setMemberId(memberId);
		query.setType(CouponType.COUPON);
		query.setUsed(false);
		query.setExpired(false);
		query.expireTime().gt(LocalDateTime.now());
		List<CouponEntity> list1 = couponService.list(query.toQueryWrapper());
		if (CollectionUtils.isEmpty(list1)) {
			return list;
		}

		List<SkuEntity> skus = skuService.listByIds(skuIds);
		List<String> spuIds = skus.stream().map(SkuEntity::getSpuId).distinct().collect(Collectors.toList());
		for (CouponEntity entity : list1) {
			String couponTemplateId = entity.getCouponTemplateId();
			CouponTemplate couponTemplate = detail(couponTemplateId);
			BigDecimal decimal = new BigDecimal("-1");
			if (couponTemplate!=null&&(couponTemplate.getLowerLimit().compareTo(decimal)==0||couponTemplate.getLowerLimit().compareTo(money)<=0)) {
				LocalDateTime startTime = couponTemplate.getStartTime();
				if (startTime != null && startTime.compareTo(LocalDateTime.now()) > 0) {
					break;
				}
				this.listAddCoupon(entity,couponTemplate,spuIds,list);
			}
		}
		return list;
	}

	private void listAddCoupon(CouponEntity entity,CouponTemplate couponTemplate,List<String> spuIds,List<Coupon> list){
		for (String spuId : spuIds) {
			if (getScopeSpu(couponTemplate, spuId)) {
				Coupon coupon = new Coupon(entity);
				coupon.setCouponTemplate(couponTemplate);
				list.add(coupon);
				break;
			}
		}
	}

	@Override
	public List<CouponTemplate> getSpuCashCouponShowList(String spuId, boolean status) {
		Check.notEmpty(spuId, "spuId is required");
		SpuEntity spu = spuService.getById(spuId);
		if (spu == null) {
			return null;
		}
		List<CouponTemplate> collect = baseMapper.searchShowList(spu.getBusdId(), status ? "1" : "0").stream()
				.filter((CouponTemplate t) -> getScopeSpu(detail(t.getId()), spuId)).collect(Collectors.toList());
		collect.forEach(a -> {
			if (checkStock(a)) {
				a.setStatus(0);
			} else {
				a.setStatus(1);
			}
		});
		return collect;
	}

	private IPage<Spu> getExcludeSpuPage(String couponTemplateId, PageRequest page,String busdId) {
		CouponScopeSpuQuery query = new CouponScopeSpuQuery();
		query.setCouponTemplateId(couponTemplateId);
		List<CouponScopeSpuEntity> list = couponScopeSpuService.list(query.toQueryWrapper());
		List<String> spuIds = list.stream().map(CouponScopeSpuEntity::getSpuId).distinct().collect(Collectors.toList());
		SpuQuery spuQuery = new SpuQuery();
		spuQuery.id().notIn(spuIds);
		spuQuery.setSkuType(SkuType.GOODS);
		spuQuery.setShowModule(SpuShowModule.GOODS);
		spuQuery.setVerifyStatus(SpuVerifyStatus.PASSED);
		spuQuery.setDel(false);
		spuQuery.setBusdId(busdId);
		spuQuery.setPublishStatus(SpuPublishStatus.UPPER);
		spuQuery.beginTime().le(LocalDateTime.now());
		spuQuery.endTime().ge(LocalDateTime.now());

		IPage<SpuEntity> entityIPage = new Page<>(page.getPage(),page.getSize(),page.getCount());
		IPage<SpuEntity> spuEntityIPage = spuService.page(entityIPage, spuQuery.toQueryWrapper());
		return spuEntityIPage.convert(Spu::new);
	}

	private IPage<Spu> getScopeSpuPage(String couponTemplateId,PageRequest page) {
		CouponScopeSpuQuery query = new CouponScopeSpuQuery();
		query.setCouponTemplateId(couponTemplateId);
		List<CouponScopeSpuEntity> list = couponScopeSpuService.list(query.toQueryWrapper());
		List<String> spuIds = list.stream().map(CouponScopeSpuEntity::getSpuId).distinct().collect(Collectors.toList());
		SpuQuery spuQuery = new SpuQuery();
		spuQuery.id().in(spuIds);
		spuQuery.setSkuType(SkuType.GOODS);
		spuQuery.setShowModule(SpuShowModule.GOODS);
		spuQuery.setDel(false);
		spuQuery.setPublishStatus(SpuPublishStatus.UPPER);
		spuQuery.setVerifyStatus(SpuVerifyStatus.PASSED);
		spuQuery.beginTime().le(LocalDateTime.now());
		spuQuery.endTime().ge(LocalDateTime.now());

		IPage<SpuEntity> entityIPage = new Page<>(page.getPage(),page.getSize(),page.getCount());
		IPage<SpuEntity> spuEntityIPage = spuService.page(entityIPage, spuQuery.toQueryWrapper());
		return spuEntityIPage.convert(Spu::new);
	}

	private List<Spu> getSpuList(List<String> spuIdList) {
		SpuQuery query = new SpuQuery();
		if (CollectionUtils.isNotEmpty(spuIdList)) {
			query.id().in(spuIdList);
		}
		// 商品必须为实物
		query.skuType().eq(SkuType.GOODS);
		// 商品必须为实物
		query.skuType().eq(SkuType.GOODS);
		// 商品为优质好货
		query.showModule().equals(SpuShowModule.GOODS);
		// 商品必须上架
		query.publishStatus().eq(SpuPublishStatus.UPPER);
		query.del().eq(true);
		query.beginTime().le(LocalDateTime.now());
		query.endTime().ge(LocalDateTime.now());
		query.verifyStatus().eq(SpuVerifyStatus.PASSED);
		List<SpuEntity> entities = spuService.list(query.toQueryWrapper());
		return entities.stream().map(Spu::new).collect(Collectors.toList());
	}
	
	@Override
	public List<Spu> getCashCouponSpuList(String couponTemplateId) {
		CouponTemplate template = this.detail(couponTemplateId);
		if (template.getScope().equals(CouponTemplateScope.ALL)) {
			return getSpuList(null);
		}
		return new ArrayList<>();
	}

	@Override
	public List<Spu> couponSelectSpu(String id) {
		return couponScopeSpuService.getSpuList(id);
	}

}